﻿using System;
using System.Linq;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;

namespace WindsorInitConfig {
    [TestFixture]
    public class SingletonPerTransient {
        [Test]
        public void tt() {
            var container = new WindsorContainer();
            container.Kernel.ComponentModelCreated += model => {
                var repodep = model.Constructors.SelectMany(c => c.Dependencies)
                    .FirstOrDefault(d => d.TargetType.IsGenericType && d.TargetType.GetGenericTypeDefinition() == typeof (IRepository<,>));
                if (repodep == null)
                    return;
                var name = Guid.NewGuid().ToString();
                container.Register(Component
                                       .For(repodep.TargetType)
                                       .ImplementedBy(typeof (EsentRepository<,>).MakeGenericType(repodep.TargetType.GetGenericArguments()))
                                       .Parameters(Parameter.ForKey("dir").Eq(model.Parameters["repodir"].Value))
                                       .Named(name));
                model.Parameters.Add(repodep.DependencyKey, "${" + name + "}");
            };
            container.Register(Component.For<Transient1>().Parameters(Parameter.ForKey("repodir").Eq("dir1")));
            container.Register(Component.For<Transient2>().Parameters(Parameter.ForKey("repodir").Eq("dir2")));
            var t1 = container.Resolve<Transient1>();
            Assert.AreEqual("dir1", t1.Repository.Dir);
            var t2 = container.Resolve<Transient2>();
            Assert.AreEqual("dir2", t2.Repository.Dir);
        }

        public class Transient1 {
            public IRepository<string, int> Repository { get; private set; }

            public Transient1(IRepository<string, int> repository) {
                Repository = repository;
            }
        }

        public class Transient2 {
            public IRepository<int, int> Repository { get; private set; }

            public Transient2(IRepository<int, int> repository) {
                Repository = repository;
            }
        }

        public interface IRepository<K, V> {
            string Dir { get; }
        }

        public class EsentRepository<K, V> : IRepository<K, V> {
            public string Dir { get; private set; }

            public EsentRepository(string dir) {
                Dir = dir;
            }
        }
    }
}